﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;
using System.Drawing.Drawing2D;
using System.Diagnostics;
using System.Drawing.Printing;
using System.Security.AccessControl;
using mshtml;
using System.Drawing.Imaging;

namespace BugSnapper
{
    public partial class ucBugSnapper : UserControl, SearchableBrowser
    {

        #region Properties Variable
        private IHTMLDocument2 doc;
        private bool updatingFontName = false;
        private bool updatingFontSize = false;
        private bool setup = false;

        public delegate void TickDelegate();

        public delegate void InstallHookHandler();
        public event InstallHookHandler OnInstallHook;
        public delegate void UnInstallHookHandler();
        public event UnInstallHookHandler OnUnInstallHook;

        public class EnterKeyEventArgs : EventArgs
        {
            private bool _cancel = false;

            public bool Cancel
            {
                get { return _cancel; }
                set { _cancel = value; }
            }

        }

        public event TickDelegate Tick;

        public event WebBrowserNavigatedEventHandler Navigated;

        public event EventHandler<EnterKeyEventArgs> EnterKeyEvent;
        #endregion
        #region Constructor
        public ucBugSnapper()
        {
            InitializeComponent();
            this.Logger = new Logger();

            this.keyboardHook = new KeyboardHook();

            #region Event Binding
            this.btnSnapAndSave.Click += new EventHandler(btnSnapAndSave_Click);
            this.btnStartSnapping.Click += new System.EventHandler(this.btnStartSnapping_Click);
            this.btnStopSnapping.Click += new System.EventHandler(this.btnStopSnapping_Click);
            this.btnSave.Click += new System.EventHandler(this.btnSave_Click);
            this.btnUnderLine.Click += new System.EventHandler(this.btnUnderLine_Click);
            this.btnItalic.Click += new System.EventHandler(this.btnItalic_Click);
            this.btnBold.Click += new EventHandler(btnBold_Click);
            this.btnDrawRectangle.Click += new System.EventHandler(this.btnDrawRectancle_Click);
            this.btnLeft.Click += new System.EventHandler(this.btnLeft_Click);
            this.btnCenter.Click += new System.EventHandler(this.btnCenter_Click);
            this.btnRight.Click += new System.EventHandler(this.btnRight_Click);
            this.btnPrint.Click += new System.EventHandler(this.btnPrint_Click);
            this.btnCut.Click += new System.EventHandler(this.btnCut_Click);
            this.btnCopy.Click += new System.EventHandler(this.btnCopy_Click);
            this.btnPaste.Click += new System.EventHandler(this.btnPaste_Click);
            this.btnDelete.Click += new System.EventHandler(this.btnDelete_Click);
            this.btnUndo.Click += new System.EventHandler(this.btnUndo_Click);
            this.btnZoomIn.Click += new System.EventHandler(this.btnZoomIn_Click);
            this.btnZoomOut.Click += new System.EventHandler(this.btnZoomOut_Click);
            this.btnBackGround.Click += new System.EventHandler(this.btnBackGround_Click);
            this.btnColor.Click += new System.EventHandler(this.btnColor_Click);
            this.btnFind.Click += new System.EventHandler(this.btnFind_Click);
            //this.btnReplace.Click += new System.EventHandler(this.btnReplace_Click);
            this.btnTop.Click += new System.EventHandler(this.btnTop_Click);
            this.btnBottom.Click += new System.EventHandler(this.btnBottom_Click);
            this.btnGlobalSettings.Click += new System.EventHandler(this.btnGlobalSettings_Click);
            this.btnFindDocument.Click += new System.EventHandler(this.btnFindDocument_Click);
            this.keyboardHook.KeyboardEvent += new KeyboardHook.KeyboardEventHandler(keyboardHook_KeyboardEvent);
            this.Timer1.Tick += new EventHandler(Timer1_Tick);
            this.btnPause.Click += new EventHandler(btnPause_Click);
            this.fontSizeComboBox.TextChanged += new EventHandler(fontSizeComboBox_TextChanged);
            this.fontSizeComboBox.KeyPress += new KeyPressEventHandler(fontSizeComboBox_KeyPress);
            this.fontSizeComboBox.Enter += new System.EventHandler(this.fontSizeComboBox_Enter);
            this.fontSizeComboBox.Leave += new System.EventHandler(this.fontSizeComboBox_Leave);
            this.fontComboBox.Enter += new EventHandler(fontComboBox_Enter);
            this.fontComboBox.Leave += new EventHandler(fontComboBox_Leave);
            this.btnLink.Click += new System.EventHandler(this.btnLink_Click);
            this.btnAddImage.Click += new EventHandler(btnAddImage_Click);
            this.btnJustifyFull.Click += new EventHandler(justifyFullButton_Click);
            this.btnIndent.Click += new EventHandler(indentButton_Click);
            this.btnOutdent.Click += new EventHandler(outdentButton_Click);
            this.btnCaptureArea.Click += new System.EventHandler(this.btnCaptureArea_Click);
            this.btnOrderedList.Click += new EventHandler(this.orderedListButton_Click);
            this.btnUnOrderedList.Click += new EventHandler(this.unorderedListButton_Click);
            this.btnRedo.Click += new EventHandler(btnRedo_Click);
            #endregion
        }
        #endregion

        #region Variables, Properties and Delegates
        private KeyboardHook keyboardHook = null;
        private int linesPrinted;
        private string[] lines;
        public System.Drawing.Rectangle RectangleBounds { get; set; }
        private delegate void GenericWindowsEventsHandler<TArgs>(object sender, TArgs e);
        private delegate void GenericHandler();
        private delegate void keyboardHookHandler_KeyboardEvent(KeyboardEvents kEvent, Keys key);
        private Logger Logger { get; set; }
        private Keys PreviousKey { get; set; }
        private Timer Timer1 = new Timer();
        public bool PauseClicked { get; set; }
        public bool RequestSave { get; set; }
        public string btnPauseText
        {
            get
            {
                return this.btnPause.Text;
            }
            set
            {
                this.btnPause.Text = value;
            }
        }
        #endregion

        #region Methods

        public void InstallHook()
        {
            try
            {
                this.UnInstallHook();
                this.OnInstallHook += keyboardHook.InstallHook;
                this.OnInstallHook();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        public void UnInstallHook()
        {
            try
            {
                if (this.OnUnInstallHook != null && this.OnUnInstallHook.GetInvocationList().Length > 0)
                {
                    int count = this.OnUnInstallHook.GetInvocationList().Length;
                    for (int i = 0; i < count; i++)
                    {
                        this.OnUnInstallHook -= keyboardHook.UninstallHook;
                    }
                }

                this.OnUnInstallHook += keyboardHook.UninstallHook;
                if (this.OnInstallHook != null && this.OnInstallHook.GetInvocationList().Length > 0)
                {
                    int count = this.OnInstallHook.GetInvocationList().Length;
                    for (int i = 0; i < count; i++)
                    {
                        this.OnInstallHook -= keyboardHook.InstallHook;
                        this.OnUnInstallHook();
                    }
                }
                this.OnUnInstallHook();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        public void PerformClosingActivities()
        {
            try
            {
                btnStopSnapping_Click(this, new EventArgs());
                if (Directory.Exists(Path.GetTempPath() + "Bug_Snapper"))
                {
                    Directory.Delete(Path.GetTempPath() + "Bug_Snapper", true);
                }
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        public Bitmap ResizeImg(Bitmap bmp, int NewWidth, int MaxHeight, bool OnlyResizeIfWider)
        {
            try
            {
                // Prevent using images internal thumbnail
                bmp.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
                bmp.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);

                if (OnlyResizeIfWider)
                {
                    if (bmp.Width <= NewWidth)
                    {
                        NewWidth = bmp.Width;
                    }
                }

                int NewHeight = bmp.Height * NewWidth / bmp.Width;
                if (NewHeight > MaxHeight)
                {
                    // Resize with height instead
                    NewWidth = bmp.Width * MaxHeight / bmp.Height;
                    NewHeight = MaxHeight;
                }

                return (bmp = ((Bitmap)((Image)bmp).GetThumbnailImage(NewWidth, NewHeight, null, IntPtr.Zero)));
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return bmp;
            }
        }

        private void SetControls(bool value)
        {
            try
            {
                this.btnStartSnapping.Enabled = !value;
                this.btnStopSnapping.Enabled = value;
                this.btnPause.Enabled = value;
                this.btnBold.Enabled = value;
                this.btnCenter.Enabled = value;
                this.btnColor.Enabled = value;
                this.btnCopy.Enabled = value;
                this.btnCut.Enabled = value;
                this.btnDelete.Enabled = value;
                this.btnDrawRectangle.Enabled = value;
                this.btnFind.Enabled = value;
                this.fontSizeComboBox.Enabled = value;
                this.fontComboBox.Enabled = value;
                this.btnItalic.Enabled = value;
                this.btnLeft.Enabled = value;
                this.btnPaste.Enabled = value;
                this.btnPrint.Enabled = value;
                //this.btnReplace.Enabled = value;
                this.btnRight.Enabled = value;
                this.btnSave.Enabled = value;
                this.btnUnderLine.Enabled = value;
                this.btnUndo.Enabled = value;
                this.btnZoomIn.Enabled = value;
                this.btnBackGround.Enabled = value;
                this.btnZoomOut.Enabled = value;
                ((Control)this.webBrowser1).Enabled = value;
                this.BodyHtml = string.Empty;
                this.btnTop.Enabled = value;
                this.btnBottom.Enabled = value;
                this.btnCaptureArea.Enabled = value;
                this.btnLink.Enabled = value;
                this.btnAddImage.Enabled = value;
                this.btnJustifyFull.Enabled = value;
                this.btnIndent.Enabled = value;
                this.btnOutdent.Enabled = value;
                this.btnUnOrderedList.Enabled = value;
                this.btnOrderedList.Enabled = value;
                this.btnRedo.Enabled = value;

                if (value)
                {
                    if (AppGlobal.TimerPeriod > 0)
                    {
                        this.Timer1.Interval = AppGlobal.TimerPeriod;
                        this.Timer1.Start();
                    }
                    this.InstallHook();
                }
                else
                {
                    this.btnStartSnapping.Select();
                    this.Timer1.Stop();
                    this.UnInstallHook();
                }
                System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ucBugSnapper));
                this.btnPause.Image = ((System.Drawing.Image)(resources.GetObject("btnPause.Image")));
                this.btnPause.Text = "Pause";
                if (this.ParentForm != null)
                {
                    (this.ParentForm as MainForm).IsSnapping = value;
                }
                this.PauseClicked = false;
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>The GetForegroundWindow function returns a handle to the foreground window.</summary>
        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();

        public void CaptureWindow(out Bitmap bmp)
        {
            try
            {
                // get te hDC of the target window
                IntPtr hdcSrc = User32.GetWindowDC(GetForegroundWindow());
                // get the size
                User32.RECT windowRect = new User32.RECT();
                User32.GetWindowRect(GetForegroundWindow(), ref windowRect);
                int width = windowRect.right - windowRect.left;
                int height = windowRect.bottom - windowRect.top;
                // create a device context we can copy to
                IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
                // create a bitmap we can copy it to,
                // using GetDeviceCaps to get the width/height
                IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height);
                // select the bitmap object
                IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap);
                // bitblt over
                GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY);
                // restore selection
                GDI32.SelectObject(hdcDest, hOld);
                // clean up
                GDI32.DeleteDC(hdcDest);
                User32.ReleaseDC(GetForegroundWindow(), hdcSrc);
                // get a .NET image object for it
                bmp = Bitmap.FromHbitmap(hBitmap);
                GDI32.DeleteObject(hBitmap);
                System.Threading.Thread.Sleep(10);
                if (AppGlobal.Compress)
                {
                    bmp = bmp.SaveJPG100();
                }
                if (AppGlobal.FitToPage)
                {
                    if (bmp.Height > 500 && bmp.Width > 700)
                    {
                        bmp = ResizeImg(bmp, 700, 500, true);
                    }
                }
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                bmp = default(Bitmap);
            }
        }

        private void GetSnap(out Bitmap bmp, string senderMethod)
        {
            if (!IsDisposed)
            {
                try
                {
                    //To Take Full Screen Including the Task Bar
                    //bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
                    //To Take Full Screen Excluding Task Bar
                    switch (senderMethod)
                    {
                        case "CaptureActiveWindow":
                            {
                                this.CaptureWindow(out bmp);
                                return;
                            }
                        case "KeyStrokeRaised":
                            {
                                this.CaptureScreen(out bmp);
                                return;
                            }
                        case "CaptureArea":
                            {
                                this.CaptureArea(out bmp);
                                return;
                            }
                    }
                    bmp = default(Bitmap);
                }
                catch (Exception ex)
                {
                    bmp = default(Bitmap);
                    this.Logger.ProcessError(ex);
                }
            }
            else
            {
                bmp = default(Bitmap);
            }
        }

        private void CaptureScreen(out Bitmap bmp)
        {
            bmp = new Bitmap(Screen.PrimaryScreen.WorkingArea.Size.Width, Screen.PrimaryScreen.WorkingArea.Size.Height);
            try
            {
                using (Graphics graphics = Graphics.FromImage(bmp))
                {
                    //set the resize quality modes to high quality
                    graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
                    graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                    graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
                    graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel;
                    try
                    {
                        graphics.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.WorkingArea.Size, CopyPixelOperation.SourceCopy);
                        System.Threading.Thread.Sleep(10);
                        if (AppGlobal.Compress)
                        {
                            bmp = bmp.SaveJPG100();
                        }
                        if (AppGlobal.FitToPage)
                        {
                            if (bmp.Height > 500 && bmp.Width > 700)
                            {
                                bmp = ResizeImg(bmp, 700, 500, true);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        bmp = default(Bitmap);
                    }
                }
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        private void CaptureArea(out Bitmap bmp)
        {

            if (this.RectangleBounds.Height > 0 && this.RectangleBounds.Width > 0)
            {
                bmp = new Bitmap(this.RectangleBounds.Width, this.RectangleBounds.Height);
            }
            else
            {
                bmp = new Bitmap(Screen.PrimaryScreen.WorkingArea.Size.Width, Screen.PrimaryScreen.WorkingArea.Size.Height);
            }
            try
            {
                using (Graphics graphics = Graphics.FromImage(bmp))
                {
                    //set the resize quality modes to high quality
                    graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
                    graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                    graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
                    graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel;
                    try
                    {
                        graphics.CopyFromScreen(this.RectangleBounds.X, this.RectangleBounds.Y, 0, 0, this.RectangleBounds.Size, CopyPixelOperation.SourceCopy);
                        System.Threading.Thread.Sleep(10);
                        if (AppGlobal.Compress)
                        {
                            bmp = bmp.SaveJPG100();
                        }
                        if (AppGlobal.FitToPage)
                        {
                            if (this.RectangleBounds.Width > 700 && this.RectangleBounds.Height > 0)
                            {
                                bmp = ResizeImg(bmp, 700, 500, true);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        bmp = default(Bitmap);
                    }
                }
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        #region MyRegion
        private void DeleteImageFromImageList()
        {
            try
            {
                this.Delete();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }
        #endregion

        static void RestartApp()
        {
            try
            {
                Application.Exit();
                Process.Start(Application.ExecutablePath, "/restart" + Process.GetCurrentProcess().Id);
            }
            catch (Exception ex)
            {
                Logger logger = new Logger();
                logger.ProcessError(ex);
            }
        }

        public void StartSnapping()
        {
            try
            {
                this.btnStartSnapping_Click(this, new EventArgs());
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        public void StopSnapping()
        {
            try
            {
                this.btnStopSnapping_Click(this, new EventArgs());
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        public void PauseSnapping()
        {
            try
            {
                this.btnPause_Click(this, new EventArgs());
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }
        #endregion

        #region Events

        void btnRedo_Click(object sender, EventArgs e)
        {
            try
            {
                this.Redo();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }


        private void fontSizeComboBox_Enter(object sender, EventArgs e)
        {
            try
            {
                this.DisableTimer();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        private void fontSizeComboBox_Leave(object sender, EventArgs e)
        {
            try
            {

            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }
        void fontComboBox_Leave(object sender, EventArgs e)
        {
            try
            {
                this.EnableTimer();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        void fontComboBox_Enter(object sender, EventArgs e)
        {
            try
            {
                this.DisableTimer();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        private void btnLink_Click(object sender, EventArgs e)
        {
            try
            {
                this.SelectLink();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        void btnAddImage_Click(object sender, EventArgs e)
        {
            try
            {
                this.DisableTimer();
                using (OpenFileDialog dlg = new OpenFileDialog())
                {
                    if (Directory.Exists(AppGlobal.RootFolderPath))
                    {
                        dlg.InitialDirectory = AppGlobal.RootFolderPath;
                    }
                    dlg.Filter = "Bitmap File (*.bmp)|*.bmp|JPG File (*.jpg)|*.jpg|JPEG File (*.jpeg)|*.jpeg|GIF File (*.gif)|*.gif|TIFF File (*.tiff)|*.tiff|TIF File (*.tif)|*.tif|PNG File (*.png)|*.png";
                    if (dlg.ShowDialog() == DialogResult.OK)
                    {
                        var path = this.FilePath.Replace(".bmp", Path.GetExtension(dlg.FileName));
                        File.Copy(dlg.FileName, path);
                        this.InsertImage(path);
                    }
                }
                this.EnableTimer();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        public void btnSnapAndSave_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        this.DisableTimer();
                        if (sender.GetType() != typeof(MainForm))
                        {
                            this.ParentForm.Hide();
                            this.Hide();
                        }
                        Bitmap bmp;
                        System.Threading.Thread.Sleep(100);
                        this.CaptureScreen(out bmp);
                        System.Threading.Thread.Sleep(100);
                        if (bmp != null)
                        {
                            using (SaveFileDialog fileDlg = new SaveFileDialog())
                            {
                                fileDlg.InitialDirectory = AppGlobal.RootFolderPath;
                                fileDlg.Filter = "Bitmap File (*.bmp)|*.bmp|JPG File (*.jpg)|*.jpg|JPEG File (*.jpeg)|*.jpeg|GIF File (*.gif)|*.gif|TIFF File (*.tiff)|*.tiff|TIF File (*.tif)|*.tif|PNG File (*.png)|*.png";
                                if (fileDlg.ShowDialog() != DialogResult.Cancel)
                                {
                                    Path.GetExtension(fileDlg.FileName);
                                    string tempFilePath = this.FilePath.ToLower().Replace(".bmp", Path.GetExtension(fileDlg.FileName));
                                    ImageFormat format = ImageFormat.Bmp;
                                    switch (Path.GetExtension(fileDlg.FileName.ToLower()))
                                    {
                                        case ".jpg":
                                        case ".jpeg":
                                            {
                                                format = ImageFormat.Jpeg;
                                                break;
                                            }
                                        case ".bmp":
                                            {
                                                format = ImageFormat.Bmp;
                                                break;
                                            }
                                        case ".gif":
                                            {
                                                format = ImageFormat.Gif;
                                                break;
                                            }
                                        case ".tif":
                                        case ".tiff":
                                            {
                                                format = ImageFormat.Tiff;
                                                break;
                                            }
                                        case ".png":
                                            {
                                                format = ImageFormat.Png;
                                                break;
                                            }
                                        default:
                                            {
                                                format = ImageFormat.Bmp;
                                                break;
                                            }
                                    }
                                    if (!string.IsNullOrEmpty(AppGlobal.WaterMarkText))
                                    {
                                        bmp = this.AddTextAsWaterMark(bmp, new SizeF(3, 3));
                                    }
                                    if (AppGlobal.DateTimeAsWaterMark)
                                    {
                                        bmp = this.AddDateTimeAsWaterMark(bmp);
                                    }
                                    bmp.Save(tempFilePath, format);
                                    File.Copy(tempFilePath, fileDlg.FileName);
                                    try
                                    {
                                        File.Delete(tempFilePath);
                                    }
                                    catch { }
                                }
                            }
                        }
                        if (sender.GetType() != typeof(MainForm))
                        {
                            this.Show();
                            this.ParentForm.Show();
                        }
                        this.EnableTimer();
                    }
                    catch (Exception ex)
                    {
                        if (sender.GetType() != typeof(MainForm))
                        {
                            this.Show();
                            this.ParentForm.Show();
                        }
                        this.EnableTimer();
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnSnapAndSave_Click), sender, e);
                }
            }
        }


        private void btnStartSnapping_Click(object sender, System.EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        if (this.btnStartSnapping.Enabled)
                        {
                            this.InstallHook();
                            this.SetControls(true);
                            this.webBrowser1.Focus();

                            // Minimize Application...
                            if (this.ParentForm != null)
                            {
                                ((MainForm)this.ParentForm).SetMainFormWindowState(FormWindowState.Minimized);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnStartSnapping_Click), sender, e);
                }
            }
        }

        private void btnStopSnapping_Click(object sender, System.EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        if (this.btnStopSnapping.Enabled)
                        {
                            this.RequestSave = false;
                            this.DisableTimer();
                            if (!string.IsNullOrEmpty(this.webBrowser1.Document.Body.InnerHtml) && MessageBox.Show("Do you wish to save the document?", "Message", MessageBoxButtons.YesNo) == DialogResult.Yes)
                            {
                                btnSave_Click(this.btnStopSnapping, e);
                            }
                            else
                            {
                                ((Control)this.webBrowser1).Enabled = false;
                            }
                            if (!this.RequestSave)
                            {
                                this.UnInstallHook();
                                SetControls(false);
                                Text = null;
                                this.BodyHtml = string.Empty;
                                GC.Collect();
                                try
                                {
                                    Directory.Delete(this.FolderPath, true);
                                }
                                catch { }
                                btnStartSnapping.Select();
                            }
                            fontComboBox.SelectedItem = "Arial";
                            this.fontSizeComboBox.SelectedItem = "1";
                            if (AppGlobal.TimerPeriod > 0 && this.btnStopSnapping.Enabled && this.RequestSave)
                            {
                                Timer1.Interval = AppGlobal.TimerPeriod;
                                Timer1.Start();
                                this.InstallHook();
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                    finally
                    {
                        ((Control)this.webBrowser1).Enabled = false;
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnStopSnapping_Click), sender, e);
                }
            }
        }

        private void keyboardHook_KeyboardEvent(KeyboardEvents kEvent, Keys key)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        if (PreviousKey == Keys.Alt && key == Keys.PrintScreen)
                        {
                            this.CaptureActiveWindow();
                            PreviousKey = key;
                            return;
                        }

                        switch (key)
                        {
                            case Keys.PrintScreen:
                                {
                                    KeyStrokeRaised();
                                    break;
                                }
                        }

                        if (btnStopSnapping.Enabled && this.webBrowser1.Focused && this.Focused)
                        {
                            //Delete
                            if (key == Keys.Delete)
                            {
                                this.DeleteImageFromImageList();
                            }
                            //Bold
                            if (PreviousKey == Keys.Control && key == Keys.B)
                            {
                                this.Bold();
                            }
                            //Underline
                            if (PreviousKey == Keys.Control && key == Keys.U)
                            {
                                this.Underline();
                            }
                            //Italic
                            if (PreviousKey == Keys.Control && key == Keys.I)
                            {
                                this.Italic();
                            }
                            //Print
                            if (PreviousKey == Keys.Control && key == Keys.P)
                            {
                                this.DisableTimer();
                                this.Print();
                                this.EnableTimer();
                            }
                            ////Paste
                            //if (PreviousKey == Keys.Control && key == Keys.V)
                            //{
                            //    this.Paste();
                            //}
                            //Copy
                            if (PreviousKey == Keys.Control && key == Keys.C)
                            {
                                this.DisableTimer();
                                this.Copy();
                                this.EnableTimer();
                            }
                            //Find
                            if (PreviousKey == Keys.Control && key == Keys.F)
                            {
                                this.DisableTimer();
                                this.btnFind_Click(this, new EventArgs());
                                this.EnableTimer();
                            }
                            //Select All
                            if (PreviousKey == Keys.Control && key == Keys.A)
                            {
                                this.DisableTimer();
                                this.SelectAll();
                                this.EnableTimer();
                            }
                            //Cut
                            if (PreviousKey == Keys.Control && key == Keys.X)
                            {
                                this.DisableTimer();
                                this.Cut();
                                this.EnableTimer();
                            }
                            //Undo
                            if (PreviousKey == Keys.Control && key == Keys.Z)
                            {
                                this.DisableTimer();
                                this.Undo();
                                this.EnableTimer();
                            }
                            //Redo
                            if (PreviousKey == Keys.Control && key == Keys.Y)
                            {
                                this.DisableTimer();
                                this.Redo();
                                this.EnableTimer();
                            }
                            //Replace
                            //if (PreviousKey == Keys.Control && key == Keys.H)
                            //    {
                            //        this.btnReplace_Click(this, new EventArgs());
                            //    }
                        }
                        PreviousKey = key;
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new keyboardHookHandler_KeyboardEvent(keyboardHook_KeyboardEvent), kEvent, key);
                }
            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        try
                        {
                            if (this.btnSave.Enabled)
                            {
                                using (SaveFileDialog saveFileDialog = new SaveFileDialog())
                                {
                                    if (Directory.Exists(AppGlobal.RootFolderPath))
                                    {
                                        saveFileDialog.InitialDirectory = AppGlobal.RootFolderPath;
                                    }
                                    if (AppGlobal.SaveDocumentAs == AppGlobal.SaveDocumentFormat.Word)
                                    {
                                        saveFileDialog.Filter = "Doc files (*.docx)|*.docx";
                                    }
                                    else if (AppGlobal.SaveDocumentAs == AppGlobal.SaveDocumentFormat.PDF)
                                    {
                                        saveFileDialog.Filter = "Pdf files (*.pdf)|*.pdf";
                                    }
                                    this.DisableTimer();
                                    if (saveFileDialog.ShowDialog() == DialogResult.Cancel)
                                    {
                                        this.RequestSave = true;
                                        this.EnableTimer();
                                        return;
                                    }
                                    #region Save the HTML in Word document and clear webbrowser
                                    if (!string.IsNullOrEmpty(saveFileDialog.FileName))
                                    {
                                        this.SuspendLayout();


                                        Microsoft.Office.Interop.Word.Application word = new Microsoft.Office.Interop.Word.Application();
                                        Microsoft.Office.Interop.Word.Document wordDoc = new Microsoft.Office.Interop.Word.Document();
                                        Object oMissing = System.Reflection.Missing.Value;
                                        wordDoc = word.Documents.Add(ref oMissing, ref oMissing, ref oMissing, ref oMissing);
                                        word.Visible = false;
                                        string fPath = this.FolderPath + "tempHTM" + DateTime.Now.ToString().Replace("/", "").Replace(" ", "").Replace(":", "").Replace(".", "").Replace("_", "") + ".htm";
                                        File.WriteAllText(fPath, this.webBrowser1.DocumentText);

                                        Object filepath = fPath;
                                        Object confirmconversion = System.Reflection.Missing.Value;
                                        Object readOnly = false;
                                        Object saveto = saveFileDialog.FileName;
                                        Object oallowsubstitution = System.Reflection.Missing.Value;

                                        wordDoc = word.Documents.Open(ref filepath, ref confirmconversion, ref readOnly, ref oMissing,
                                                                      ref oMissing, ref oMissing, ref oMissing, ref oMissing,
                                                                      ref oMissing, ref oMissing, ref oMissing, ref oMissing,
                                                                      ref oMissing, ref oMissing, ref oMissing, ref oMissing);
                                        object fileFormat = Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatXMLDocument;
                                        if (AppGlobal.SaveDocumentAs == AppGlobal.SaveDocumentFormat.PDF)
                                        {
                                            fileFormat = Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatPDF;
                                        }
                                        wordDoc.Activate();
                                        wordDoc.SaveAs(ref saveto, ref fileFormat, ref oMissing, ref oMissing, true,
                                                       ref oMissing, false, true, true, ref oMissing,
                                                       ref oMissing, ref oMissing, true, true, ref oMissing,
                                                       ref oMissing);

                                        foreach (Microsoft.Office.Interop.Word.InlineShape s in wordDoc.InlineShapes)
                                        {
                                            if (s.Type == Microsoft.Office.Interop.Word.WdInlineShapeType.wdInlineShapeLinkedPicture)
                                            {
                                                s.LinkFormat.SavePictureWithDocument = true;
                                            }
                                        }

                                        wordDoc.Save();
                                        wordDoc.Close();
                                        word.Quit();
                                    }
                                    #endregion
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            this.Logger.ProcessError(ex);
                            if (AppGlobal.SaveDocumentAs == AppGlobal.SaveDocumentFormat.PDF)
                            {
                                MessageBox.Show("Unable to Save the Document as PDF. Please try and run Patch.bat from application folder. If issue still persists contact Application Vendor.");
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                    finally
                    {
                        try
                        {
                            Directory.Delete(this.FolderPath, true);
                        }
                        catch { }

                        ((Control)this.webBrowser1).Enabled = false;
                        this.UnInstallHook();
                        SetControls(false);
                        this.BodyHtml = string.Empty;
                        GC.Collect();
                        this.ResumeLayout();
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnSave_Click), sender, e);
                }
            }
        }
        public delegate void InitializeBugSnapperHandler();
        public void InitializeBugSnapper()
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        //this.Height = Screen.PrimaryScreen.WorkingArea.Height;
                        //this.Width = Screen.PrimaryScreen.WorkingArea.Width;
                        SetupEvents();
                        SetupBrowser();
                        SetupFontComboBox();

                        this.SetControls(false);
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new InitializeBugSnapperHandler(InitializeBugSnapper));
                }
            }

        }
        private void btnDrawRectancle_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        #region Draw Rectangle
                        if (btnStopSnapping.Enabled)
                        {
                            foreach (HtmlElement item in this.webBrowser1.Document.Body.GetElementsByTagName("img"))
                            {
                                item.Click += new HtmlElementEventHandler(this.htmlElement_Click);
                            }
                        }
                        #endregion
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnDrawRectancle_Click), sender, e);
                }
            }
        }

        public void DisableTimer()
        {
            try
            {
                this.Timer1.Stop();
                this.UnInstallHook();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }
        public void EnableTimer()
        {
            try
            {
                if (AppGlobal.TimerPeriod > 0 && !btnStartSnapping.Enabled)
                {
                    Timer1.Interval = AppGlobal.TimerPeriod;
                    Timer1.Start();
                }
                this.InstallHook();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }
        private void btnPrint_Click(object sender, System.EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        this.Print();
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnPrint_Click), sender, e);
                }
            }
        }

        private void btnFindDocument_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        using (frmFindDocument findDocument = new frmFindDocument())
                        {
                            this.DisableTimer();
                            findDocument.ShowDialog();
                            if (AppGlobal.TimerPeriod > 0 && !btnStartSnapping.Enabled)
                            {
                                Timer1.Interval = AppGlobal.TimerPeriod;
                                this.EnableTimer();
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnFindDocument_Click), sender, e);
                }
            }
        }

        private void btnBold_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        this.Bold();
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnBold_Click), sender, e);
                }
            }
        }

        private void btnUnderLine_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        this.Underline();
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnUnderLine_Click), sender, e);
                }
            }
        }

        private void btnItalic_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        this.Italic();
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnItalic_Click), sender, e);
                }
            }
        }


        /// <summary>
        /// Get/Set the editor's foreground (text) color for the current selection.
        /// </summary>
        [Browsable(false)]
        public Color EditorForeColor
        {
            get
            {
                try
                {
                    if (ReadyState != ReadyState.Complete)
                    {
                        return Color.Black;
                    }
                    return ConvertToColor(doc.queryCommandValue("ForeColor").ToString());
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                    return Color.Black;
                }
            }
            set
            {
                try
                {
                    string colorstr = string.Format("#{0:X2}{1:X2}{2:X2}", value.R, value.G, value.B);
                    webBrowser1.Document.ExecCommand("ForeColor", false, colorstr);
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                }
            }
        }

        public ReadyState ReadyState
        {
            get
            {
                try
                {
                    switch (doc.readyState.ToLower())
                    {
                        case "uninitialized":
                            return ReadyState.Uninitialized;
                        case "loading":
                            return ReadyState.Loading;
                        case "loaded":
                            return ReadyState.Loaded;
                        case "interactive":
                            return ReadyState.Interactive;
                        case "complete":
                            return ReadyState.Complete;
                        default:
                            return ReadyState.Uninitialized;
                    }
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                    return ReadyState.Uninitialized;
                }
            }
        }

        /// <summary>
        /// Get the current selection type.
        /// </summary>
        public SelectionType SelectionType
        {
            get
            {
                try
                {
                    switch (doc.selection.type.ToLower())
                    {
                        case "text":
                            return SelectionType.Text;
                        case "control":
                            return SelectionType.Control;
                        case "none":
                            return SelectionType.None;
                        default:
                            return SelectionType.None;
                    }
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                    return SelectionType.None;
                }
            }
        }

        /// <summary>
        /// Get/Set the current font size.
        /// </summary>
        [Browsable(false)]
        public FontSize FontSize
        {
            get
            {
                try
                {
                    if (ReadyState != ReadyState.Complete)
                        return FontSize.NA;
                    string fontSize = Convert.ToString(doc.queryCommandValue("FontSize"));
                    switch (fontSize)
                    {
                        case "1":
                            return FontSize.One;
                        case "2":
                            return FontSize.Two;
                        case "3":
                            return FontSize.Three;
                        case "4":
                            return FontSize.Four;
                        case "5":
                            return FontSize.Five;
                        case "6":
                            return FontSize.Six;
                        case "7":
                            return FontSize.Seven;
                        default:
                            return FontSize.NA;
                    }
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                    return FontSize.NA;
                }
            }
            set
            {
                try
                {
                    int sz;
                    switch (value)
                    {
                        case FontSize.One:
                            sz = 1;
                            break;
                        case FontSize.Two:
                            sz = 2;
                            break;
                        case FontSize.Three:
                            sz = 3;
                            break;
                        case FontSize.Four:
                            sz = 4;
                            break;
                        case FontSize.Five:
                            sz = 5;
                            break;
                        case FontSize.Six:
                            sz = 6;
                            break;
                        case FontSize.Seven:
                            sz = 7;
                            break;
                        default:
                            sz = 7;
                            break;
                    }
                    webBrowser1.Document.ExecCommand("FontSize", false, sz.ToString());
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                }
            }
        }

        /// <summary>
        /// Get/Set the editor's background color for the current selection.
        /// </summary>
        [Browsable(false)]
        public Color EditorBackColor
        {
            get
            {
                try
                {
                    if (ReadyState != ReadyState.Complete)
                        return Color.White;
                    return ConvertToColor(doc.queryCommandValue("BackColor").ToString());
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                    return Color.White;
                }
            }
            set
            {
                try
                {
                    string colorstr =
                                string.Format("#{0:X2}{1:X2}{2:X2}", value.R, value.G, value.B);
                    webBrowser1.Document.ExecCommand("BackColor", false, colorstr);
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                }
            }
        }

        /// <summary>
        /// Initiate the foreground (text) color dialog for the current selection.
        /// </summary>
        public void SelectForeColor()
        {
            try
            {
                Color color = EditorForeColor;
                if (ShowColorDialog(ref color))
                    EditorForeColor = color;
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Initiate the background color dialog for the current selection.
        /// </summary>
        public void SelectBackColor()
        {
            try
            {
                Color color = EditorBackColor;
                if (ShowColorDialog(ref color))
                    EditorBackColor = color;
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Convert the custom integer (B G R) format to a color object.
        /// </summary>
        /// <param name="clrs">the custorm color as a string</param>
        /// <returns>the color</returns>
        private static Color ConvertToColor(string clrs)
        {
            try
            {
                int red, green, blue;
                // sometimes clrs is HEX organized as (RED)(GREEN)(BLUE)
                if (clrs.StartsWith("#"))
                {
                    int clrn = Convert.ToInt32(clrs.Substring(1), 16);
                    red = (clrn >> 16) & 255;
                    green = (clrn >> 8) & 255;
                    blue = clrn & 255;
                }
                else // otherwise clrs is DECIMAL organized as (BlUE)(GREEN)(RED)
                {
                    int clrn = Convert.ToInt32(clrs);
                    red = clrn & 255;
                    green = (clrn >> 8) & 255;
                    blue = (clrn >> 16) & 255;
                }
                Color incolor = Color.FromArgb(red, green, blue);
                return incolor;
            }
            catch (Exception ex)
            {
                return Color.Black;
            }
        }

        private void btnColor_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        this.DisableTimer();
                        this.SelectForeColor();
                        this.EnableTimer();
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnColor_Click), sender, e);
                }
            }
        }

        private void btnBackGround_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        this.DisableTimer();
                        this.SelectBackColor();
                        this.EnableTimer();
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnBackGround_Click), sender, e);
                }
            }
        }

        private void btnCut_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        this.Cut();
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnCut_Click), sender, e);
                }
            }
        }

        private void btnCopy_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        Clipboard.Clear();
                        this.Copy();
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnCopy_Click), sender, e);
                }
            }
        }

        private void btnPaste_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        this.Paste();
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnPaste_Click), sender, e);
                }
            }
        }

        private void btnUndo_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        this.Undo();
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnUndo_Click), sender, e);
                }
            }
        }

        private void btnLeft_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        this.JustifyLeft();
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnLeft_Click), sender, e);
                }
            }
        }

        private void btnCenter_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        this.JustifyCenter();
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnCenter_Click), sender, e);
                }
            }
        }

        private void btnRight_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        this.JustifyRight();
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnRight_Click), sender, e);
                }
            }
        }

        private void btnZoomIn_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        if (this.webBrowser1.ZoomFactor < 400)
                        {
                            this.webBrowser1.Zoom(this.webBrowser1.ZoomFactor + 10);
                        }

                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnRight_Click), sender, e);
                }
            }
        }

        private void btnZoomOut_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        if (this.webBrowser1.ZoomFactor > 10)
                        {
                            this.webBrowser1.Zoom(this.webBrowser1.ZoomFactor - 10);
                        }
                        else
                        {
                            this.webBrowser1.ZoomFactor = 10;
                        }
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnZoomOut_Click), sender, e);
                }
            }
        }

        private void btnFind_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        this.DisableTimer();
                        using (SearchDialog dlg = new SearchDialog(this))
                        {
                            dlg.ShowDialog(this);
                        }
                        this.EnableTimer();
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnFind_Click), sender, e);
                }
            }
        }

        #region Replace button code
        //private void btnReplace_Click(object sender, EventArgs e)
        //{
        //    if (!IsDisposed)
        //    {
        //        if (!InvokeRequired)
        //        {
        //            try
        //            {
        //                //frmReplace replace = new frmReplace(this);
        //            }
        //            catch (Exception ex)
        //            {
        //                this.Logger.ProcessError(ex);
        //            }
        //        }
        //        else
        //        {
        //            Invoke(new GenericWindowsEventsHandler<EventArgs>(btnFind_Click), sender, e);
        //        }
        //    }
        //} 
        #endregion

        private void btnDelete_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        this.DeleteImageFromImageList();
                        this.Delete();
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnDelete_Click), sender, e);
                }
            }
        }

        private void btnTop_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        this.webBrowser1.Focus();
                        this.webBrowser1.Document.Window.ScrollTo(0, 10);
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnTop_Click), sender, e);
                }
            }
        }

        private void btnBottom_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        this.webBrowser1.Focus();
                        this.webBrowser1.Document.Window.ScrollTo(0, this.webBrowser1.Document.Body.ScrollRectangle.Height);
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnBottom_Click), sender, e);
                }
            }
        }

        private void btnGlobalSettings_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        using (frmGlobalSettings frmGB = new frmGlobalSettings())
                        {
                            this.DisableTimer();
                            frmGB.ShowDialog();
                            this.EnableTimer();
                        }
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnGlobalSettings_Click), sender, e);
                }
            }
        }
        public delegate void SetWindowStateOfBugSnapperHandler(FormWindowState windowState);
        public void SetWindowStateOfBugSnapper(FormWindowState windowState)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        if (this.ParentForm != null)
                        {
                            ((MainForm)this.ParentForm).SetMainFormWindowState(windowState);
                        }
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new SetWindowStateOfBugSnapperHandler(SetWindowStateOfBugSnapper), windowState);
                }
            }
        }

        private void btnCaptureArea_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {

                        if (btnStopSnapping.Enabled)
                        {
                            this.DisableTimer();
                            this.ParentForm.Hide();
                            this.Hide();
                            Bitmap bmp;

                            using (GetSelectionArea getSelectionArea = new GetSelectionArea())
                            {
                                getSelectionArea.ShowDialog();
                                this.RectangleBounds = getSelectionArea.RectangleBounds;

                                this.CaptureArea(out bmp);
                                if (bmp != null)
                                {
                                    this.InsertImage(this.SaveImage(bmp));
                                }
                            }
                            System.Threading.Thread.Sleep(100);
                            this.Show();
                            this.ParentForm.Show();
                            this.EnableTimer();
                        }
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                        this.Show();
                        this.ParentForm.Show();
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(btnGlobalSettings_Click), sender, e);
                }
            }
        }

        private void Timer1_Tick(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        if (btnStopSnapping.Enabled)
                        {
                            if (!this.PauseClicked)
                            {
                                this.KeyStrokeRaised();
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(Timer1_Tick), sender, e);
                }
            }
        }

        private void btnPause_Click(object sender, EventArgs e)
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        this.PauseClicked = !this.PauseClicked;
                        if (btnStopSnapping.Enabled)
                        {
                            if (this.PauseClicked)
                            {
                                this.UnInstallHook();
                                this.btnPause.Image = ((Image)(new ImageConverter()).ConvertFrom(Properties.Resources.Pause_Normal_Red));
                                this.btnPause.Text = "Resume";
                            }
                            else
                            {
                                System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ucBugSnapper));
                                this.InstallHook();
                                this.btnPause.Image = ((System.Drawing.Image)(resources.GetObject("btnPause.Image")));
                                this.btnPause.Text = "Pause";
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericWindowsEventsHandler<EventArgs>(Timer1_Tick), sender, e);
                }
            }
        }
        #endregion

        #region Browser Events and Methods
        private void SetupEvents()
        {
            try
            {
                webBrowser1.Navigated += new WebBrowserNavigatedEventHandler(webBrowser1_Navigated);
                webBrowser1.GotFocus += new EventHandler(webBrowser1_GotFocus);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// When this control receives focus, it transfers focus to the 
        /// document body.
        /// </summary>
        /// <param name="sender">the sender</param>
        /// <param name="e">EventArgs</param>
        private void webBrowser1_GotFocus(object sender, EventArgs e)
        {
            try
            {
                SuperFocus();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// This is called when the initial html/body framework is set up, 
        /// or when document.DocumentText is set.  At this point, the 
        /// document is editable.
        /// </summary>
        /// <param name="sender">sender</param>
        /// <param name="e">navigation args</param>
        void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
        {
            try
            {
                SetBackgroundColor(BackColor);
                if (Navigated != null)
                {
                    Navigated(this, e);
                }
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Add document body, turn on design mode on the whole document, 
        /// and overred the context menu
        /// </summary>
        private void SetupBrowser()
        {
            try
            {
                webBrowser1.DocumentText = "<html><body></body></html>";
                doc = webBrowser1.Document.DomDocument as IHTMLDocument2;
                doc.designMode = "On";
                webBrowser1.Document.ContextMenuShowing += new HtmlElementEventHandler(Document_ContextMenuShowing);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Set the focus on the document body.  
        /// </summary>
        private void SuperFocus()
        {
            try
            {
                if (webBrowser1.Document != null &&
                       webBrowser1.Document.Body != null)
                    webBrowser1.Document.Body.Focus();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Get/Set the background color of the editor.
        /// Note that if this is called before the document is rendered and 
        /// complete, the navigated event handler will set the body's 
        /// background color based on the state of BackColor.
        /// </summary>
        [Browsable(true)]
        public override Color BackColor
        {
            get
            {
                try
                {
                    return base.BackColor;
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                    return Color.Black;
                }
            }
            set
            {
                try
                {
                    base.BackColor = value;
                    if (ReadyState == ReadyState.Complete)
                    {
                        SetBackgroundColor(value);
                    }
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                }
            }
        }

        /// <summary>
        /// Set the background color of the body by setting it's CSS style
        /// </summary>
        /// <param name="value">the color to use for the background</param>
        private void SetBackgroundColor(Color value)
        {
            try
            {
                if (webBrowser1.Document != null &&
                        webBrowser1.Document.Body != null)
                    webBrowser1.Document.Body.Style =
                        string.Format("background-color: {0}", value.Name);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Clear the contents of the document, leaving the body intact.
        /// </summary>
        public void Clear()
        {
            try
            {
                if (webBrowser1.Document.Body != null)
                {
                    webBrowser1.Document.Body.InnerHtml = "";
                    this.webBrowser1.Zoom(100);
                }
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Get the web browser component's document
        /// </summary>
        public HtmlDocument Document
        {
            get
            {
                try
                {
                    return webBrowser1.Document;
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                    return null;
                }
            }
        }

        /// <summary>
        /// Document text should be used to load/save the entire document, 
        /// including html and body start/end tags.
        /// </summary>
        [Browsable(false)]
        public string DocumentText
        {
            get
            {
                try
                {
                    return webBrowser1.DocumentText;
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                    return string.Empty;
                }
            }
            set
            {
                try
                {
                    webBrowser1.DocumentText = value;
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                }
            }
        }

        /// <summary>
        /// Get the html document title from document.
        /// </summary>
        [Browsable(false)]
        public string DocumentTitle
        {
            get
            {
                try
                {
                    return webBrowser1.DocumentTitle;
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                    return string.Empty;
                }
            }
        }

        /// <summary>
        /// Get/Set the contents of the document Body, in html.
        /// </summary>
        [Browsable(false)]
        public string BodyHtml
        {
            get
            {
                try
                {
                    if (webBrowser1.Document != null &&
                                webBrowser1.Document.Body != null)
                    {
                        return webBrowser1.Document.Body.InnerHtml;
                    }
                    else
                        return string.Empty;
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                    return string.Empty;
                }
            }
            set
            {
                try
                {
                    if (webBrowser1.Document.Body != null)
                        webBrowser1.Document.Body.InnerHtml = value;
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                }
            }
        }

        /// <summary>
        /// Get/Set the documents body as text.
        /// </summary>
        [Browsable(false)]
        public string BodyText
        {
            get
            {
                try
                {
                    if (webBrowser1.Document != null &&
                                webBrowser1.Document.Body != null)
                    {
                        return webBrowser1.Document.Body.InnerText;
                    }
                    else
                        return string.Empty;
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                    return string.Empty;
                }
            }
            set
            {
                try
                {
                    if (webBrowser1.Document.Body != null)
                        webBrowser1.Document.Body.InnerText = value;
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                }
            }
        }

        /// <summary>
        /// Determine the status of the Undo command in the document editor.
        /// </summary>
        /// <returns>whether or not an undo operation is currently valid</returns>
        public bool CanUndo()
        {
            try
            {
                return doc.queryCommandEnabled("Undo");
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return false;
            }
        }

        /// <summary>
        /// Determine the status of the Redo command in the document editor.
        /// </summary>
        /// <returns>whether or not a redo operation is currently valid</returns>
        public bool CanRedo()
        {
            try
            {
                return doc.queryCommandEnabled("Redo");
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return false;
            }
        }

        /// <summary>
        /// Determine the status of the Cut command in the document editor.
        /// </summary>
        /// <returns>whether or not a cut operation is currently valid</returns>
        public bool CanCut()
        {
            try
            {
                return doc.queryCommandEnabled("Cut");
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return false;
            }
        }

        /// <summary>
        /// Determine the status of the Copy command in the document editor.
        /// </summary>
        /// <returns>whether or not a copy operation is currently valid</returns>
        public bool CanCopy()
        {
            try
            {
                return doc.queryCommandEnabled("Copy");
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return false;
            }
        }

        /// <summary>
        /// Determine the status of the Paste command in the document editor.
        /// </summary>
        /// <returns>whether or not a copy operation is currently valid</returns>
        public bool CanPaste()
        {
            try
            {
                return doc.queryCommandEnabled("Paste");
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return false;
            }
        }

        /// <summary>
        /// Determine the status of the Delete command in the document editor.
        /// </summary>
        /// <returns>whether or not a copy operation is currently valid</returns>
        public bool CanDelete()
        {
            try
            {
                return doc.queryCommandEnabled("Delete");
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return false;
            }
        }

        /// <summary>
        /// Determine whether the current block is left justified.
        /// </summary>
        /// <returns>true if left justified, otherwise false</returns>
        public bool IsJustifyLeft()
        {
            try
            {
                return doc.queryCommandState("JustifyLeft");
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return false;
            }
        }

        /// <summary>
        /// Determine whether the current block is right justified.
        /// </summary>
        /// <returns>true if right justified, otherwise false</returns>
        public bool IsJustifyRight()
        {
            try
            {
                return doc.queryCommandState("JustifyRight");
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return false;
            }
        }

        /// <summary>
        /// Determine whether the current block is center justified.
        /// </summary>
        /// <returns>true if center justified, false otherwise</returns>
        public bool IsJustifyCenter()
        {
            try
            {
                return doc.queryCommandState("JustifyCenter");
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return false;
            }
        }

        /// <summary>
        /// Determine whether the current block is full justified.
        /// </summary>
        /// <returns>true if full justified, false otherwise</returns>
        public bool IsJustifyFull()
        {
            try
            {
                return doc.queryCommandState("JustifyFull");
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return false;
            }
        }

        /// <summary>
        /// Determine whether the current selection is in Bold mode.
        /// </summary>
        /// <returns>whether or not the current selection is Bold</returns>
        public bool IsBold()
        {
            try
            {
                return doc.queryCommandState("Bold");
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return false;
            }
        }

        /// <summary>
        /// Determine whether the current selection is in Italic mode.
        /// </summary>
        /// <returns>whether or not the current selection is Italicized</returns>
        public bool IsItalic()
        {
            try
            {
                return doc.queryCommandState("Italic");
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return false;
            }
        }

        /// <summary>
        /// Determine whether the current selection is in Underline mode.
        /// </summary>
        /// <returns>whether or not the current selection is Underlined</returns>
        public bool IsUnderline()
        {
            try
            {
                return doc.queryCommandState("Underline");
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return false;
            }
        }

        /// <summary>
        /// Determine whether the current paragraph is an ordered list.
        /// </summary>
        /// <returns>true if current paragraph is ordered, false otherwise</returns>
        public bool IsOrderedList()
        {
            try
            {
                return doc.queryCommandState("InsertOrderedList");
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return false;
            }
        }

        /// <summary>
        /// Determine whether the current paragraph is an unordered list.
        /// </summary>
        /// <returns>true if current paragraph is ordered, false otherwise</returns>
        public bool IsUnorderedList()
        {
            try
            {
                return doc.queryCommandState("InsertUnorderedList");
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return false;
            }
        }

        /// <summary>
        /// Called when the editor context menu should be displayed.
        /// The return value of the event is set to false to disable the 
        /// default context menu.  A custom context menu (contextMenuStrip1) is 
        /// shown instead.
        /// </summary>
        /// <param name="sender">the sender</param>
        /// <param name="e">HtmlElementEventArgs</param>
        private void Document_ContextMenuShowing(object sender, HtmlElementEventArgs e)
        {
            try
            {
                e.ReturnValue = false;
                btnCut.Enabled = CanCut();
                btnCopy.Enabled = CanCopy();
                btnPaste.Enabled = CanPaste();
                btnDelete.Enabled = CanDelete();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        #region Font Size
        /// <summary>
        /// Called when a key is pressed on the font size combo box.
        /// The font size in the boxy box is set to the key press value.
        /// </summary>
        /// <param name="sender">the sender</param>
        /// <param name="e">KeyPressEventArgs</param>
        private void fontSizeComboBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            try
            {
                if (Char.IsNumber(e.KeyChar))
                {
                    e.Handled = true;
                    if (e.KeyChar <= '7' && e.KeyChar > '0')
                        fontSizeComboBox.Text = e.KeyChar.ToString();
                }
                else if (!Char.IsControl(e.KeyChar))
                {
                    e.Handled = true;
                }
                this.webBrowser1.Focus();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Set editor's current selection to the value of the font size combo box.
        /// Ignore if the timer is currently updating the font size to synchronize 
        /// the font size combo box with the editor's current selection.
        /// </summary>
        /// <param name="sender">the sender</param>
        /// <param name="e">EventArgs</param>
        private void fontSizeComboBox_TextChanged(object sender, EventArgs e)
        {
            try
            {
                if (updatingFontSize)
                {
                    this.webBrowser1.Focus();
                    return;
                }
                switch (fontSizeComboBox.Text.Trim())
                {
                    case "1":
                        FontSize = FontSize.One;
                        break;
                    case "2":
                        FontSize = FontSize.Two;
                        break;
                    case "3":
                        FontSize = FontSize.Three;
                        break;
                    case "4":
                        FontSize = FontSize.Four;
                        break;
                    case "5":
                        FontSize = FontSize.Five;
                        break;
                    case "6":
                        FontSize = FontSize.Six;
                        break;
                    case "7":
                        FontSize = FontSize.Seven;
                        break;
                    default:
                        FontSize = FontSize.Seven;
                        break;
                }
                this.webBrowser1.Focus();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Populate the font combo box and autocomplete handlers.
        /// Add a text changed handler to the font combo box to handle new font selections.
        /// </summary>
        private void SetupFontComboBox()
        {
            try
            {
                AutoCompleteStringCollection ac = new AutoCompleteStringCollection();
                foreach (FontFamily fam in FontFamily.Families)
                {
                    fontComboBox.Items.Add(fam.Name);
                    ac.Add(fam.Name);
                }
                fontComboBox.Leave += new EventHandler(fontComboBox_TextChanged);
                fontComboBox.AutoCompleteSource = AutoCompleteSource.CustomSource;
                fontComboBox.AutoCompleteCustomSource = ac;
                fontComboBox.SelectedItem = "Arial";
                this.fontSizeComboBox.SelectedItem = "1";
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Called when the font combo box has changed.
        /// Ignores the event when the timer is updating the font combo Box 
        /// to synchronize the editor selection with the font combo box.
        /// </summary>
        /// <param name="sender">the sender</param>
        /// <param name="e">EventArgs</param>
        private void fontComboBox_TextChanged(object sender, EventArgs e)
        {
            if (updatingFontName) return;
            FontFamily ff;
            try
            {
                ff = new FontFamily(fontComboBox.Text);
            }
            catch (Exception)
            {
                updatingFontName = true;
                fontComboBox.Text = FontName.GetName(0);
                updatingFontName = false;
                return;
            }
            FontName = ff;
        }

        #endregion


        /// <summary>
        /// Embed a break at the current selection.
        /// This is a placeholder for future functionality.
        /// </summary>
        public void EmbedBr()
        {
            try
            {
                IHTMLTxtRange range =
                        doc.selection.createRange() as IHTMLTxtRange;
                range.pasteHTML("<br/>");
                range.collapse(false);
                range.select();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        public string FolderPath
        {
            get
            {
                try
                {
                    string folderPath = Convert.ToString(System.Environment.CurrentDirectory) + @"\tmpImages\";
                    if (!Directory.Exists(folderPath))
                    {
                        Directory.CreateDirectory(folderPath);
                    }
                    return folderPath;
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                    return string.Empty;
                }
            }
        }

        public string FilePath
        {
            get
            {
                try
                {
                    return this.FolderPath + "Img" + DateTime.Now.ToString().Replace("/", "").Replace(" ", "").Replace(":", "").Replace(".", "").Replace("_", "") + ".bmp";
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                    return string.Empty;
                }
            }
        }

        /// <summary>
        /// Paste the clipboard text into the current selection.
        /// This is a placeholder for future functionality.
        /// </summary>
        private void SuperPaste()
        {
            try
            {
                if (Clipboard.ContainsText())
                {
                    IHTMLTxtRange range =
                        doc.selection.createRange() as IHTMLTxtRange;
                    range.pasteHTML(Clipboard.GetText(TextDataFormat.Text));
                    range.collapse(false);
                    range.select();
                }
                if (Clipboard.ContainsImage())
                {
                    IDataObject data = Clipboard.GetDataObject();
                    this.InsertImage(this.SaveImage((Bitmap)data.GetData(DataFormats.Bitmap, true)));
                }
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Print the current document
        /// </summary>
        public void Print()
        {
            try
            {
                webBrowser1.Document.ExecCommand("Print", true, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Insert a paragraph break
        /// </summary>
        public void InsertParagraph()
        {
            try
            {
                webBrowser1.Document.ExecCommand("InsertParagraph", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Insert a horizontal rule
        /// </summary>
        public void InsertBreak()
        {
            try
            {
                webBrowser1.Document.ExecCommand("InsertHorizontalRule", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Select all text in the document.
        /// </summary>
        public void SelectAll()
        {
            try
            {
                webBrowser1.Document.ExecCommand("SelectAll", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Undo the last operation
        /// </summary>
        public void Undo()
        {
            try
            {
                webBrowser1.Document.ExecCommand("Undo", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Redo based on the last Undo
        /// </summary>
        public void Redo()
        {
            try
            {
                webBrowser1.Document.ExecCommand("Redo", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Cut the current selection and place it in the clipboard.
        /// </summary>
        public void Cut()
        {
            try
            {
                webBrowser1.Document.ExecCommand("Cut", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Paste the contents of the clipboard into the current selection.
        /// </summary>
        public void Paste()
        {
            try
            {
                webBrowser1.Document.ExecCommand("Paste", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Copy the current selection into the clipboard.
        /// </summary>
        public void Copy()
        {
            try
            {
                webBrowser1.Document.ExecCommand("Copy", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Toggle the ordered list property for the current paragraph.
        /// </summary>
        public void OrderedList()
        {
            try
            {
                webBrowser1.Document.ExecCommand("InsertOrderedList", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Toggle the unordered list property for the current paragraph.
        /// </summary>
        public void UnorderedList()
        {
            try
            {
                webBrowser1.Document.ExecCommand("InsertUnorderedList", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Toggle the left justify property for the currnet block.
        /// </summary>
        public void JustifyLeft()
        {
            try
            {
                webBrowser1.Document.ExecCommand("JustifyLeft", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Toggle the right justify property for the current block.
        /// </summary>
        public void JustifyRight()
        {
            try
            {
                webBrowser1.Document.ExecCommand("JustifyRight", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Toggle the center justify property for the current block.
        /// </summary>
        public void JustifyCenter()
        {
            try
            {
                webBrowser1.Document.ExecCommand("JustifyCenter", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Toggle the full justify property for the current block.
        /// </summary>
        public void JustifyFull()
        {
            try
            {
                webBrowser1.Document.ExecCommand("JustifyFull", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Toggle bold formatting on the current selection.
        /// </summary>
        public void Bold()
        {
            try
            {
                webBrowser1.Document.ExecCommand("Bold", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Toggle italic formatting on the current selection.
        /// </summary>
        public void Italic()
        {
            try
            {
                webBrowser1.Document.ExecCommand("Italic", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Toggle underline formatting on the current selection.
        /// </summary>
        public void Underline()
        {
            try
            {
                webBrowser1.Document.ExecCommand("Underline", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Delete the current selection.
        /// </summary>
        public void Delete()
        {
            try
            {
                webBrowser1.Document.ExecCommand("Delete", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Insert an imange.
        /// </summary>
        public void InsertImage()
        {
            try
            {
                webBrowser1.Document.ExecCommand("InsertImage", true, null);
                this.webBrowser1.Document.Body.InnerHtml += "<br><br>";
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }
        public void InsertImage(string path)
        {
            try
            {
                this.webBrowser1.Document.Body.ScrollIntoView(false);
                HtmlElement htmlElement = this.webBrowser1.Document.CreateElement("img");
                htmlElement.SetAttribute("src", path);
                htmlElement.Click += new HtmlElementEventHandler(htmlElement_Click);
                this.webBrowser1.Document.Body.AppendChild(htmlElement);
                this.webBrowser1.Document.Body.InnerHtml += "<br><br>";
                //this.webBrowser1.Document.Body.InnerHtml+= "<img src='" + path + "' /><br><br>";
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        void htmlElement_Click(object sender, HtmlElementEventArgs e)
        {
            try
            {
                var SelectedElement = this.webBrowser1.Document.GetElementFromPoint(e.OffsetMousePosition);
                if (!string.IsNullOrEmpty(SelectedElement.GetAttribute("src")))
                {
                    Uri url = new Uri(SelectedElement.GetAttribute("src"));
                    var SelectedImagePath = url.LocalPath;


                    this.DisableTimer();
                    using (frmHighLigtImage frmHighLightImage = new frmHighLigtImage())
                    {
                        if (!string.IsNullOrEmpty(SelectedImagePath))
                        {
                            frmHighLightImage.ImageToEdit = SelectedImagePath;
                            frmHighLightImage.SelectedElement = SelectedElement;
                            frmHighLightImage.NewFilePath = this.FilePath;
                            frmHighLightImage.ShowDialog();
                        }
                        if (btnStopSnapping.Enabled)
                        {
                            foreach (HtmlElement item in this.webBrowser1.Document.Body.GetElementsByTagName("img"))
                            {
                                item.Click -= new HtmlElementEventHandler(this.htmlElement_Click);
                            }
                        }
                        doc = webBrowser1.Document.DomDocument as IHTMLDocument2;
                        doc.designMode = "On";
                        this.EnableTimer();
                    }
                }
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        private string SaveImage(Bitmap bmp)
        {
            try
            {
                string path = this.FilePath;
                string extension = string.Empty;
                switch (AppGlobal.SaveAsImageFormat)
                {
                    case AppGlobal.ImageFormats.BMP:
                        {
                            extension = ".bmp";
                            break;
                        }
                    case AppGlobal.ImageFormats.JPEG:
                        {
                            extension = ".jpeg";
                            break;
                        }
                    case AppGlobal.ImageFormats.GIF:
                        {
                            extension = ".gif";
                            break;
                        }
                    case AppGlobal.ImageFormats.TIFF:
                        {
                            extension = ".tiff";
                            break;
                        }
                    case AppGlobal.ImageFormats.PNG:
                        {
                            extension = ".png";
                            break;
                        }
                    default:
                        {
                            extension = ".bmp";
                            break;
                        }

                }
                //bmp.Save(path.ToLower().Replace(".bmp", extension), System.Drawing.Imaging.ImageFormat.Bmp);
                if (!string.IsNullOrEmpty(AppGlobal.WaterMarkText))
                {
                    bmp = this.AddTextAsWaterMark(bmp, new SizeF(3, 3));
                }
                if (AppGlobal.DateTimeAsWaterMark)
                {
                    bmp = this.AddDateTimeAsWaterMark(bmp);
                }
                bmp.Save(path, System.Drawing.Imaging.ImageFormat.Bmp);
                return path;
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return string.Empty;
            }
        }

        private System.Drawing.Bitmap AddTextAsWaterMark(Bitmap bmp, SizeF shadowOffset)
        {
            try
            {
                if (!string.IsNullOrEmpty(AppGlobal.WaterMarkText))
                {
                    string sWaterMark = AppGlobal.WaterMarkText;
                    int fontsize = 10;

                    Font font = new Font("Verdana", fontsize, FontStyle.Bold);
                    Graphics drawing = Graphics.FromImage(bmp);

                    //measure the string to see how big the image needs to be
                    SizeF textSize = drawing.MeasureString(sWaterMark, font);
                    float x, y;

                    x = bmp.Width / 2 - textSize.Width / 2;
                    y = (int)((bmp.Height / 10) * 8.5);

                    Color textColor = Color.Transparent;
                    if (x > -1 && y > -1)
                    {
                        textColor = this.IdealTextColor(bmp.GetPixel((int)x, (int)y));
                    }
                    Color shadowColor;
                    if (textColor == Color.Black)
                    {
                        shadowColor = Color.White;
                    }
                    else
                    {
                        shadowColor = Color.Black;
                    }
                    //create a brush for the text
                    Brush shadowBrush = new SolidBrush(shadowColor); // <-- Here
                    Brush textBrush = new SolidBrush(textColor);

                    drawing.DrawString(sWaterMark, font, shadowBrush, x + shadowOffset.Width, y + shadowOffset.Height); // <-- Here
                    drawing.DrawString(sWaterMark, font, textBrush, x, y);
                    drawing.Save();

                    textBrush.Dispose();
                    drawing.Dispose();
                }
                return bmp;
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return bmp;
            }
        }
        private System.Drawing.Bitmap AddDateTimeAsWaterMark(Bitmap bmp)
        {
            try
            {
                if (AppGlobal.DateTimeAsWaterMark)
                {
                    Font font = new Font("Verdana", 8, FontStyle.Regular);
                    Graphics drawing = Graphics.FromImage(bmp);

                    //measure the string to see how big the image needs to be
                    SizeF textSize = drawing.MeasureString(DateTime.Now.ToString(), font);
                    float x, y;

                    x = bmp.Width / 2 - textSize.Width / 2;
                    if (!string.IsNullOrEmpty(AppGlobal.WaterMarkText))
                    {
                        y = (int)(((bmp.Height / 10) * 8.5)) - 10;
                    }
                    else
                    {
                        y = (int)((bmp.Height / 10) * 8.5);
                    }

                    Color textColor = Color.Transparent;
                    if (x > -1 && y > -1)
                    {
                        textColor = this.IdealTextColor(bmp.GetPixel((int)x, (int)y));
                    }
                    //create a brush for the text
                    Brush textBrush = new SolidBrush(textColor);
                    drawing.DrawString(DateTime.Now.ToString(), font, textBrush, x, y);

                    drawing.Save();

                    textBrush.Dispose();
                    drawing.Dispose();
                }
                return bmp;
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return bmp;
            }
        }

        private Color IdealTextColor(Color bg)
        {
            try
            {
                int nThreshold = 105;
                int bgDelta = Convert.ToInt32((bg.R * 0.299) + (bg.G * 0.587) +
                                              (bg.B * 0.114));

                Color foreColor = (255 - bgDelta < nThreshold) ? Color.Black : Color.White;
                return foreColor;
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return Color.Black;
            }
        }

        /// <summary>
        /// Indent the current paragraph.
        /// </summary>
        public void Indent()
        {
            try
            {
                webBrowser1.Document.ExecCommand("Indent", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Outdent the current paragraph.
        /// </summary>
        public void Outdent()
        {
            try
            {
                webBrowser1.Document.ExecCommand("Outdent", false, null);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Insert a link at the current selection.
        /// </summary>
        /// <param name="url">The link url</param>
        public void InsertLink(string url)
        {
            try
            {
                webBrowser1.Document.ExecCommand("CreateLink", false, url);
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }


        /// <summary>
        /// Get/Set the current font name.
        /// </summary>
        [Browsable(false)]
        public FontFamily FontName
        {
            get
            {
                try
                {
                    if (ReadyState != ReadyState.Complete)
                        return null;
                    string name = doc.queryCommandValue("FontName") as string;
                    if (name == null) return null;
                    return new FontFamily(name);
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                    return new FontFamily("Arial");
                }
            }
            set
            {
                try
                {
                    if (value != null)
                        webBrowser1.Document.ExecCommand("FontName", false, value.Name);
                }
                catch (Exception ex)
                {
                    this.Logger.ProcessError(ex);
                }
            }
        }


        /// <summary>
        /// Show the interactive Color dialog.
        /// </summary>
        /// <param name="color">the input and output color</param>
        /// <returns>true if dialog accepted, false if dialog cancelled</returns>
        private bool ShowColorDialog(ref Color color)
        {
            try
            {
                bool selected;
                using (ColorDialog dlg = new ColorDialog())
                {
                    dlg.SolidColorOnly = true;
                    dlg.AllowFullOpen = false;
                    dlg.AnyColor = false;
                    dlg.FullOpen = false;
                    dlg.CustomColors = null;
                    dlg.Color = color;
                    if (dlg.ShowDialog(this) == DialogResult.OK)
                    {
                        selected = true;
                        color = dlg.Color;
                    }
                    else
                    {
                        selected = false;
                    }
                }
                return selected;
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return false;
            }
        }

        /// <summary>
        /// Show a custom insert link dialog, and create the link.
        /// </summary>
        public void SelectLink()
        {
            try
            {
                this.DisableTimer();
                using (LinkDialog dlg = new LinkDialog())
                {
                    dlg.ShowDialog(this.ParentForm);
                    if (!dlg.Accepted) return;
                    string link = dlg.URI;
                    if (link == null || link.Length == 0)
                    {
                        MessageBox.Show(this.ParentForm, "Invalid URL");
                        return;
                    }
                    InsertLink(dlg.URL);
                    this.EnableTimer();
                }
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Called when the image button on the toolstrip is clicked.
        /// </summary>
        /// <param name="sender">the sender</param>
        /// <param name="e">EventArgs</param>
        private void imageButton_Click(object sender, EventArgs e)
        {
            try
            {
                InsertImage();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Called when the outdent button on the toolstrip is clicked.
        /// </summary>
        /// <param name="sender">the sender</param>
        /// <param name="e">EventArgs</param>
        private void outdentButton_Click(object sender, EventArgs e)
        {
            try
            {
                Outdent();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Called when the indent button on the toolstrip is clicked.
        /// </summary>
        /// <param name="sender">the sender</param>
        /// <param name="e">EventArgs</param>
        private void indentButton_Click(object sender, EventArgs e)
        {
            try
            {
                Indent();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Search the document from the current selection, and reset the 
        /// the selection to the text found, if successful.
        /// </summary>
        /// <param name="text">the text for which to search</param>
        /// <param name="forward">true for forward search, false for backward</param>
        /// <param name="matchWholeWord">true to match whole word, false otherwise</param>
        /// <param name="matchCase">true to match case, false otherwise</param>
        /// <returns></returns>
        public bool Search(string text, bool forward, bool matchWholeWord, bool matchCase)
        {
            try
            {
                bool success = false;
                if (webBrowser1.Document != null)
                {
                    IHTMLDocument2 doc =
                        webBrowser1.Document.DomDocument as IHTMLDocument2;
                    IHTMLBodyElement body = doc.body as IHTMLBodyElement;
                    if (body != null)
                    {
                        IHTMLTxtRange range;
                        if (doc.selection != null)
                        {
                            range = doc.selection.createRange() as IHTMLTxtRange;
                            IHTMLTxtRange dup = range.duplicate();
                            dup.collapse(true);
                            // if selection is degenerate, then search whole body
                            if (range.isEqual(dup))
                            {
                                range = body.createTextRange();
                            }
                            else
                            {
                                if (forward)
                                    range.moveStart("character", 1);
                                else
                                    range.moveEnd("character", -1);
                            }
                        }
                        else
                            range = body.createTextRange();
                        int flags = 0;
                        if (matchWholeWord) flags += 2;
                        if (matchCase) flags += 4;
                        success =
                            range.findText(text, forward ? 999999 : -999999, flags);
                        if (success)
                        {
                            range.select();
                            range.scrollIntoView(!forward);
                        }
                    }
                }
                return success;
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
                return false;
            }
        }

        /// <summary>
        /// Event handler for the ordered list toolbar button
        /// </summary>
        /// <param name="sender">the sender</param>
        /// <param name="e">EventArgs</param>
        private void orderedListButton_Click(object sender, EventArgs e)
        {
            try
            {
                OrderedList();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Event handler for the unordered list toolbar button
        /// </summary>
        /// <param name="sender">the sender</param>
        /// <param name="e">EventArgs</param>
        private void unorderedListButton_Click(object sender, EventArgs e)
        {
            try
            {
                UnorderedList();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        /// <summary>
        /// Event handler for the full justify toolbar button.
        /// </summary>
        /// <param name="sender">the sender</param>
        /// <param name="e">EventArgs</param>
        private void justifyFullButton_Click(object sender, EventArgs e)
        {
            try
            {
                JustifyFull();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }

        private void CaptureActiveWindow()
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {
                        Bitmap bmp;
                        this.GetSnap(out bmp, "CaptureActiveWindow");
                        if (bmp != null)
                        {
                            this.InsertImage(this.SaveImage(bmp));
                        }
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericHandler(CaptureActiveWindow));
                }
            }
        }

        public void KeyStrokeRaised()
        {
            if (!IsDisposed)
            {
                if (!InvokeRequired)
                {
                    try
                    {

                        Bitmap bmp;
                        this.GetSnap(out bmp, "KeyStrokeRaised");
                        if (bmp != null)
                        {
                            this.InsertImage(this.SaveImage(bmp));
                        }
                    }
                    catch (Exception ex)
                    {
                        this.Logger.ProcessError(ex);
                    }
                }
                else
                {
                    Invoke(new GenericHandler(KeyStrokeRaised));
                }
            }
        }

        #endregion

        public void btnAboutUs_Click(object sender, EventArgs e)
        {
            try
            {
                this.DisableTimer();
                using (AboutBox aboutBox = new AboutBox())
                {
                    aboutBox.ShowDialog();
                }
                this.EnableTimer();
            }
            catch (Exception ex)
            {
                this.Logger.ProcessError(ex);
            }
        }
    }

    #region Enumrations
    /// <summary>
    /// Enumeration of possible font sizes for the Editor component
    /// </summary>
    public enum FontSize
    {
        One,
        Two,
        Three,
        Four,
        Five,
        Six,
        Seven,
        NA
    }

    public enum SelectionType
    {
        Text,
        Control,
        None
    }

    public enum ReadyState
    {
        Uninitialized,
        Loading,
        Loaded,
        Interactive,
        Complete
    }
    #endregion
}
